package com.charles.seckillsystem.service.impl;

import com.charles.seckillapi.domain.SysGood;
import com.charles.seckillapi.domain.SysOrder;
import com.charles.seckillcommon.core.constants.CacheConstants;
import com.charles.seckillcommon.core.exceptions.ServiceException;
import com.charles.seckillcommon.core.utils.UUIDUtil;
import com.charles.seckillcommon.redis.service.RedisService;
import com.charles.seckillsystem.rocketMQ.producer.OrderProducer;
import com.charles.seckillsystem.service.SysGoodService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author Charles-H
 * <p>
 * 产品业务层实现类
 */
@Service
public class SysGoodServiceImpl implements SysGoodService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedissonClient redissonClient;

    @Resource
    private OrderProducer orderProducer;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String seckillGood(Long userId, Long goodId) {
        RLock lock = redissonClient.getLock("seckill:" + goodId);
        String orderId = null;

        try {
            // 尝试获取锁，等待10秒，锁自动释放时间为30秒
            boolean locked = lock.tryLock(10, 30, TimeUnit.SECONDS);

            if (locked) {
                SysGood good = redisService.getCacheObject(CacheConstants.GOOD_ID + goodId);

                /* 校验产品信息 */
                if (good == null || good.getStart_time().after(new Date(System.currentTimeMillis()))) {
                    throw new ServiceException("秒杀尚未开始!");
                }

                if (good.getEnd_time().before(new Date(System.currentTimeMillis()))) {
                    throw new ServiceException("非常抱歉,秒杀已结束");
                }

                if (good.getRemain() <= 0) {
                    throw new ServiceException("非常抱歉,库存已被抢购完");
                }

                // 每个用户只能购买一次该产品(Redis中查询是否存在产品和用户关联的订单)
                String oid = redisService.getCacheObject(CacheConstants.STORE_ORDER_ID + userId + goodId);
                if (oid != null && !oid.isEmpty()) {
                    SysOrder order = redisService.getCacheObject(CacheConstants.ORDER_ID + oid);
                    if (order != null) {
                        if (order.getStatus().equals("0")) throw new ServiceException("您已抢购,请查看未支付订单");
                        else throw new ServiceException("每个产品只能抢购1次");
                    }
                }

                // 减库,创建订单
                good.setRemain(good.getRemain() - 1);
                redisService.setCacheObject(CacheConstants.GOOD_ID + goodId, good);
                SysOrder order = new SysOrder();
                orderId = UUIDUtil.fastSimpleUUID();
                order.setOrder_id(orderId);
                order.setGood_id(goodId);
                order.setUser_id(userId);
                order.setStatus("0");
                order.setCreate_time(new Date());
                // 将订单存入redis中
                redisService.setCacheObject(CacheConstants.STORE_ORDER_ID + userId + goodId, orderId);
                redisService.setCacheObject(CacheConstants.ORDER_ID + orderId, order);
                // 开启延时消息队列，30分钟后触发，判断订单是否支付
                orderProducer.checkOrder(userId, goodId);
            } else {
                throw new ServiceException("抱歉，活动太火爆，请稍后再试");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new ServiceException("抱歉，服务端异常，请稍后再试");
        } finally {
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

        return orderId;
    }

}
